#include <iostream>
#include <fstream>
#include <getopt.h>

#include "bayesianclustering.h"


using namespace std;

//Global Variables
//*******************************
char *program = NULL;
int Block[20]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
int step=500;
bool ctrl=false;
const int ReadSize=2000;
int MaxiterBlockSize=500;
BayesianClusteringResult** BlockResult;
int SeqNum=0;
int PrevIterk=0;
int Finalk;
int Maxiter=200;
string* FinalCenterID;
string* FinalCenterSeq;
double* FinalSD;
int* FinalSize;
string** FinalMembership=NULL;
//************************************

bool ChompFile(char*, int);
bool ChompFile(int);
//void MergeResult(int);
void MergeUsingBC();
void InterResultRead(int);

int main(int argc, char* argv[])
{
	int next_option;
	/* A string listing valid short options letters. */
	const char* const short_options = "i:o:b:gse:m:z:";
	/* An array describing valid long options. */
	const struct option long_options[] = {
		{"input", 0, NULL, 'i'},
		{"output", 0, NULL, 'o'},
		{"block", 0, NULL, 'b'},
		{"genus", 0, NULL, 'g'},
		{"species", 0, NULL, 's'},
		{"step", 0, NULL, 'e'},
		{"maxiter", 0, NULL, 'm'},
		{"maxiterblocksize", 0, NULL, 'z'},
		{NULL, 0, NULL, 0}
	};
	program = argv[0];
    char* fname;
	char* oname;
	time_t start,stop;
    fstream finalout;
	/* Process the arguments */
	do{
		next_option = getopt_long(argc, argv, short_options, long_options, NULL);
		switch(next_option){
			case 'i': 
                fname=new char[strlen(optarg)+1];
                memset(fname,0x00,sizeof(char)*(strlen(optarg)+1));
				strcpy(fname,optarg);
				break;
			case 'o':
                oname=new char[strlen(optarg)+1];
                memset(oname,0x00,sizeof(char)*(strlen(optarg)+1));
                strcpy(oname,optarg);
                finalout.open(oname, ios_base::out);
                if(finalout.fail()) 
                    cout<<"cannot open output file"<<endl;
                break;
            case 'b':
                 Block[0]=atoi(optarg);
                 break;
            case 'g':
                 ctrl=true;
                 break;
            case 's':
                 ctrl=false;
                 break;
            case 'e':
                 step=atoi(optarg);
                 break;
            case 'm':
                 Maxiter=atoi(optarg);
                 break;
            case 'z':
                 MaxiterBlockSize=atoi(optarg);
                 break;
			case -1: /* Done with options */
				break;
			default: /* Unexpected */
				cout<<"Unexpected argument was taken."<<endl;
		}
	}while(next_option != -1);
	start=time(NULL);
	BlockResult=new BayesianClusteringResult*[Maxiter];
	BlockResult[0]=new BayesianClusteringResult[Block[0]];
    if(!ChompFile(fname, Block[0]))
        return 0;
    for(int i=0;i<Block[0];i++)
    {
        char Buf[ReadSize];
        itoa(i+1,Buf,10);
        string BlockFnameNum(Buf);
        string BlockFnameString="BlockSeq"+BlockFnameNum;
        const char* BlockFname=BlockFnameString.c_str();
        BayesianClustering(BlockFname, step, ctrl, BlockResult[0][i],0);
        finalout<<"[0]["<<i<<"]"<<" ";
    } 
    for(int i=1;i<Maxiter;i++)
    {
        InterResultRead(i-1);
        if((Finalk>=(double)0.9*PrevIterk)&&(i>1))
        {
            Maxiter=i-1;                 
            break;
        }//if
        if(Finalk>MaxiterBlockSize)
        {
            PrevIterk=Finalk;
            Block[i]=Finalk/MaxiterBlockSize+1;
            if(!ChompFile(Block[i]))
            {
                cout<<"Chomp Fail!"<<endl;
                return 0;
            }
            BlockResult[i]=new BayesianClusteringResult[Block[i]];
            for(int j=0;j<Block[i];j++)
            {
                char Buf[ReadSize];
                itoa(j+1,Buf,10);
                string BlockFnameNum(Buf);
                string BlockFnameString="BlockSeq"+BlockFnameNum;
                const char* BlockFname=BlockFnameString.c_str();
                BayesianClustering(BlockFname, step, ctrl, BlockResult[i][j],i);
                finalout<<"["<<i<<"]["<<j<<"]"<<" ";
                cout<<"BayesianClusteringCompleted"<<endl;
            }//j
            if(i==Maxiter-1)
            {
                InterResultRead(i);
                Maxiter=i;
            }
        }//if
        else
        {
            Maxiter=i-1;
            break;
        }//else
    }//i
    finalout<<endl;
    finalout<<"Merging Using BC"<<endl;
    MergeUsingBC();
    /*
    for(int i=0;i<Block;i++)
        MergeResult(i);
    */       
    //***************output result***************************************
    finalout<<Finalk<<endl;
    for(int i=0;i<Finalk;i++)
    {
        finalout<<FinalCenterID[i]<<" "<<FinalSize[i]<<" "<<FinalSD[i]<<endl;
    }
    for(int i=0;i<Finalk;i++)
    {
        finalout<<FinalCenterID[i]<<endl;
        finalout<<FinalCenterSeq[i]<<endl;
    }
    for(int i=0;i<Finalk;i++)
    {
        finalout<<FinalCenterID[i]<<" ";
        for(int j=0;j<FinalSize[i];j++)
            finalout<<FinalMembership[i][j]<<",";
        finalout<<endl;
    }
    finalout.close();
    cout<<"output done"<<endl;
    //******************************************************************
    //**********Free Memory*********************************************
    for(int i=0;i<Maxiter+1;i++)
    {
        for(int j=0;j<Block[i];j++)
        {
            for(int l=0; l<BlockResult[i][j].ClusterNumber; l++)
            {
                delete[] BlockResult[i][j].ClusterMember[l];
                delete[] BlockResult[i][j].ClusterMemberFlag[l];
                delete[] BlockResult[i][j].ClusterCenterID[l];
                delete[] BlockResult[i][j].ClusterCenterSeq[l];
                delete[] BlockResult[i][j].ClusterMemberSeq[l];
            }//l
            delete[] BlockResult[i][j].ClusterMemberSeq;
            delete[] BlockResult[i][j].ClusterMember;
            delete[] BlockResult[i][j].ClusterMemberFlag;
            delete[] BlockResult[i][j].ClusterCenterID;
            delete[] BlockResult[i][j].ClusterCenterSeq;
            delete[] BlockResult[i][j].ClusterStandardDeviation;
            delete[] BlockResult[i][j].ClusterSize;
            delete[] BlockResult[i][j].ClusterIterationSize;
        }//j
        delete[] BlockResult[i];
    }
    delete[] BlockResult;
    delete[] FinalCenterID;
    delete[] FinalCenterSeq;
    delete[] FinalSD;
    delete[] FinalSize;
    for(int i=0;i<Finalk;i++)
        delete[] FinalMembership[i];
    delete[] FinalMembership;
    delete[] fname;
    delete[] oname;
    //**********************************************
    stop=time(NULL);
    cout<<"Time Cost Is "<<stop-start<<" Sec"<<endl;
    system("pause");
    return 1;    
}

bool ChompFile(char* fname, int block)
{
    fstream in,out;
    string ResultName;
    string ResultNamePrefix="BlockSeq";
    string ResultNameNum="1";
    string Line;
    char Buffer[ReadSize];
    char temp[ReadSize];
    in.open(fname);
    if(in.fail())
    {
        cout<<"Read Fasta File Error"<<endl;
        return 0;
    }
    while(!in.eof())
    {
        in.getline(temp, ReadSize);
        if(temp[0]=='>')
            SeqNum++;
    }
    if(SeqNum==0)
    {
        cout<<"Not A Valid Fasta File!"<<endl;
        return 0;
    }    
    in.clear();   
    in.seekg(0,ios::beg);
    cout<<SeqNum<<endl;
    ResultName=ResultNamePrefix+ResultNameNum; 
    out.open(ResultName.c_str(),ios_base::out);
    if(out.fail())
    {
        cout<<"Write Fasta File Error"<<endl;
    }
    in.getline(temp,ReadSize);
    Line.assign(temp);
    if(temp[0]!='>')
    {
        cout<<"Bad Header"<<endl;
        return 0;
    }
    out<<Line<<endl;
    in.getline(temp,ReadSize);
    Line.assign(temp);
    for(int i=0; i<SeqNum; i++)
    {
        while(temp[0]!='>')
        {
            out<<Line<<endl;
            in.getline(temp,ReadSize);
            if(temp[0] == '\n' || temp[0] == '\0') break;
            Line.assign(temp);
        }
        if(((i-1)*block)/SeqNum!=(i*block)/SeqNum)
        {
            out.close();
            itoa((i*block)/SeqNum+1, Buffer, 10);
            ResultNameNum.assign(Buffer);
            ResultName=ResultNamePrefix+ResultNameNum;
            out.open(ResultName.c_str(),ios_base::out);
            if(out.fail())
            {
                cout<<"Write Fasta File Error"<<endl;
            }
        }
        if(i<SeqNum-1)
        {
            out<<Line<<endl;
            in.getline(temp,ReadSize);
            Line.assign(temp);
        }
        else
            out.close();
    }
    return 1;
}

bool ChompFile(int block)
{
    int tempstat=0;
    fstream in,out;
    string ResultName;
    string ResultNamePrefix="BlockSeq";
    string ResultNameNum="1";
    string Line;
    int tempint;
    double tempdouble;
    char Buffer[ReadSize];
    char temp[ReadSize];
    in.open("TempCenters");
    if(in.fail())
    {
        cout<<"Read Inter Result Fasta File Error"<<endl;
        return 0;
    }
    while(!in.eof())
    {
        in.getline(temp, ReadSize);
        if(temp[0]=='>')
            tempstat++;
    }
    if(tempstat==0)
    {
        cout<<"Not A Valid Fasta File!"<<endl;
        return 0;
    }    
    in.clear();   
    in.seekg(0,ios::beg);
    cout<<"Number of Seqs in File Before Chomp = "<<tempstat<<endl;
    ResultName=ResultNamePrefix+ResultNameNum; 
    out.open(ResultName.c_str(),ios_base::out);
    if(out.fail())
    {
        cout<<"Write Fasta File Error"<<endl;
    }
    for(int i=0;i<Finalk;i++)
    {
        if(((i-1)*block)/Finalk!=(i*block)/Finalk)
        {
            out.close();
            itoa((i*block)/Finalk+1, Buffer, 10);
            ResultNameNum.assign(Buffer);
            ResultName=ResultNamePrefix+ResultNameNum;
            out.open(ResultName.c_str(),ios_base::out);
            if(out.fail())
            {
                cout<<"Write Fasta File Error"<<endl;
            }
        }
        //*******Center Seq ID**********
        in.getline(temp,ReadSize);
        Line.assign(temp);
        out<<Line<<endl;
        //*******Center Seq************
        in.getline(temp,ReadSize);
        Line.assign(temp);
        out<<Line<<endl;
        //********Abudance and Sigma********
        in>>tempint;
        out<<tempint<<endl;
        in>>tempdouble;
        out<<tempdouble<<endl;
        in.getline(temp,ReadSize);
        //***********Eigen Seqs**************
        for(int j=0;j<MIN(tempint,20);j++)
        {
            in.getline(temp,ReadSize);
            Line.assign(temp);
            out<<Line<<endl;
        }
        if(i==Finalk-1)
            out.close();
    }
    return 1;
}

/*
void MergeResult(int a)
{
    bool flag;
    if(a==0)
    {
        FinalCenterID=new string[SeqNum];
        FinalCenterSeq=new string[SeqNum];
        FinalSize=new int[SeqNum];
        FinalSD=new double[SeqNum];
    }
    for(int i=0;i<BlockResult[a].ClusterNumber;i++)
    {
            flag=true;
            for(int j=0;j<Finalk;j++)
            {
                int matrix = EDNAFULL;
           	    alignment (*alignTool) (const char *, const char *, alignment, int, int) = NULL, align = {0, 0, 0};
                alignTool = NW_alignmentEx;
			    align = alignTool(FinalCenterSeq[j].c_str(), BlockResult[a].ClusterCenterSeq[i], align, matrix, 1);
			    double d=(1.0-(double)align.matches/(double)SHORT_ALIGN(align))*100.0;
		        if(d>15)
		            continue;
                else
                {
                    int m=BlockResult[a].ClusterSize[i];
                    int n=FinalSize[j];
                    double SD1=BlockResult[a].ClusterStandardDeviation[i];
                    double SD2=FinalSD[j];
                    double Y1=(SD1*SD1*m+(SD1+d/2)*(SD1+d/2)*n)/(m+n);
                    double Y2=((SD1+d/2)*(SD1+d/2)*m+SD2*SD2*n)/(m+n);
                    double Y3=(SD1*SD1*m+SD2*SD2*n)/(m+n);
                    double MY=MIN(Y1,Y2);
                    if((Y1<(2+(int)ctrl*3)*(2+(int)ctrl*3))||(Y2<(2+(int)ctrl*3)*(2+(int)ctrl*3)))
                    //if((sqrt((double)(m*m+n*n)/(m+n)/(m+n)*(pow(SD1,4)+pow(SD2,4)))<(2+(int)ctrl*3)*(2+(int)ctrl*3)))
                    {
                        if(MY==Y1)
                            FinalCenterSeq[j].assign(BlockResult[a].ClusterCenterSeq[i]);
                        FinalSize[j]+=m;
                        FinalSD[j]=sqrt(Y3);
                        flag=false;
                        cout<<"Merge ["<<a<<"]["<<i<<"] To ["<<j<<"]"<<endl;
                        break;
                    }
                    else
                        continue;
                }
            }
            if(flag==true)
            {
                FinalCenterID[Finalk].assign(BlockResult[a].ClusterCenterID[i]);
                FinalCenterSeq[Finalk].assign(BlockResult[a].ClusterCenterSeq[i]);
                FinalSize[Finalk]=BlockResult[a].ClusterSize[i];
                FinalSD[Finalk]=BlockResult[a].ClusterStandardDeviation[i];
                Finalk++;
                cout<<"Add ["<<a<<"]["<<i<<"]"<<endl;
            }
    }
//**********final refine***************
    if(a==Block-1){
    for(int i=Finalk-1;i>-1;i--)
    {
            for(int j=0;j<i;j++)
            {
                int matrix = EDNAFULL;
           	    alignment (*alignTool) (const char *, const char *, alignment, int, int) = NULL, align = {0, 0, 0};
                alignTool = NW_alignmentEx;
			    align = alignTool(FinalCenterSeq[j].c_str(), FinalCenterSeq[i].c_str(), align, matrix, 1);
			    double d=(1.0-(double)align.matches/(double)LONG_ALIGN(align))*100.0;
		        if(d>15)
		            continue;
                else
                {
                    int m=FinalSize[i];
                    int n=FinalSize[j];
                    double SD1=FinalSD[i];
                    double SD2=FinalSD[j];
                    double Y1=(SD1*SD1*m+(SD1+d/2)*(SD1+d/2)*n)/(m+n);
                    double Y2=((SD1+d/2)*(SD1+d/2)*m+SD2*SD2*n)/(m+n);
                    double MY=MIN(Y1,Y2);
                    if((Y1<(2+(int)ctrl*3)*(2+(int)ctrl*3))||(Y2<(2+(int)ctrl*3)*(2+(int)ctrl*3)))
                    //if((sqrt((double)(m*m+n*n)/(m+n)/(m+n)*(pow(SD1,4)+pow(SD2,4)))<(2+(int)ctrl*3)*(2+(int)ctrl*3)))
                    {
                        if(MY==Y1)
                            FinalCenterSeq[j]=FinalCenterSeq[i];
                        FinalSize[j]+=m;
                        FinalSD[j]=sqrt(MY);
                        cout<<"Merge ["<<i<<"] To ["<<j<<"]"<<endl;
                        Finalk--;
                        break;
                    }
                    else
                        continue;
                }
            }
    }
    }
    return;
}
*/

void MergeUsingBC()
{
    cout<<"MergingUsingBC"<<endl;
    BayesianClusteringResult MergeCenterResult;
    BayesianClustering("TempCenters",Finalk*10, ctrl, MergeCenterResult, 20);
    cout<<"Bayesian Clustering Completed"<<endl;
    Finalk=MergeCenterResult.ClusterNumber;
    FinalCenterID=new string[Finalk];
    FinalCenterSeq=new string[Finalk];
    FinalSize=new int[Finalk];
    FinalSD=new double[Finalk];
    FinalMembership=new string*[Finalk];
    string** TempFinalMembership;
    TempFinalMembership=new string*[Finalk];
    memset(FinalSize,0,sizeof(int)*Finalk);
    for(int i=0;i<Finalk;i++)
    {
        FinalCenterID[i].assign(MergeCenterResult.ClusterCenterID[i]);
        FinalCenterSeq[i].assign(MergeCenterResult.ClusterCenterSeq[i]);
        FinalSD[i]=MergeCenterResult.ClusterStandardDeviation[i];
        TempFinalMembership[i]=new string[SeqNum];
        for(int p=0;p<MergeCenterResult.ClusterIterationSize[i];p++)
        {
            for(int j=0;j<Block[Maxiter];j++)
            {
                for(int l=0;l<BlockResult[Maxiter][j].ClusterNumber;l++)
                {
                    if(strcmp(MergeCenterResult.ClusterMember[i][p].c_str(),BlockResult[Maxiter][j].ClusterCenterID[l])==0)
                    {                                                                                                                                                                
                            for(int q=0;q<BlockResult[Maxiter][j].ClusterIterationSize[l];q++)
                            {
                                if(BlockResult[Maxiter][j].ClusterMemberFlag[l][q]==true)
                                {
                                    cout<<"Redundant Sequence Detected: "<<BlockResult[Maxiter][j].ClusterMember[l][q]<<endl;
                                }
                                else
                                {
                                    BlockResult[Maxiter][j].ClusterMemberFlag[l][q]=true;
                                    TempFinalMembership[i][FinalSize[i]]=BlockResult[Maxiter][j].ClusterMember[l][q];
                                    FinalSize[i]++;                                    
                                }
                            }//q
                    }//if
                }//l
            }//j
        }//p
    }//i
    int totalsize1,totalsize2;
    for(int i=0;i<Maxiter+1;i++)
    {
        totalsize1=0;
        totalsize2=0;
        for(int j=0;j<Block[i];j++)
            totalsize1+=BlockResult[i][j].ClusterNumber;
        cout<<"Total Number of Clusters "<<totalsize1<<endl;
        totalsize1=0;
        for(int j=0;j<Block[i];j++)
            for(int l=0;l<BlockResult[i][j].ClusterNumber;l++)
            {
                totalsize1+=BlockResult[i][j].ClusterIterationSize[l];
                totalsize2+=BlockResult[i][j].ClusterSize[l];
            }
       cout<<"Total Seq Nums in Clusters "<<totalsize2<<" ,While Iteration Seq Nums Is "<<totalsize1<<endl;  
    }
    totalsize1=0;
    for(int i=0;i<Finalk;i++)
        totalsize1+=FinalSize[i];
    cout<<"Currently Assigned Seq Num is "<<totalsize1<<endl;
    /*
    for(int i=0;i<Block[Maxiter];i++)
        for(int j=0;j<BlockResult[Maxiter][i].ClusterNumber;j++)
            for(int l=0;l<BlockResult[Maxiter][i].ClusterIterationSize[j];l++)
                if(BlockResult[Maxiter][i].ClusterMemberFlag[j][l]==false)
                    cout<<"Missing Sequence Detected: "<<BlockResult[Maxiter][i].ClusterMember[j][l]<<endl;
    */
    while((Maxiter--)>=0)
    {
        int TempFinalSize[Finalk];
        memcpy(TempFinalSize, FinalSize, sizeof(int)*Finalk);
        for(int i=0;i<Finalk;i++)
        {
            for(int p=0;p<TempFinalSize[i];p++)
            {
                for(int j=0;j<Block[Maxiter];j++)
                {
                    for(int l=0;l<BlockResult[Maxiter][j].ClusterNumber;l++)
                    {
                       if(strcmp(TempFinalMembership[i][p].c_str(),BlockResult[Maxiter][j].ClusterCenterID[l])==0)
                       {
                           for(int q=0;q<BlockResult[Maxiter][j].ClusterIterationSize[l];q++)
                           {
                               if(strcmp(BlockResult[Maxiter][j].ClusterMember[l][q].c_str(),BlockResult[Maxiter][j].ClusterCenterID[l])!=0)
                               {
                                    if(BlockResult[Maxiter][j].ClusterMemberFlag[l][q]==true)
                                    {
                                        cout<<"Redundant Sequence Detected: "<<BlockResult[Maxiter][j].ClusterMember[l][q]<<endl;
                                    }
                                    else
                                    {
                                        BlockResult[Maxiter][j].ClusterMemberFlag[l][q]=true;
                                        TempFinalMembership[i][FinalSize[i]]=BlockResult[Maxiter][j].ClusterMember[l][q];
                                        FinalSize[i]++; 
                                    }
                               }//if
                           }//q
                       }//if
                   }//l
                }//j
            }//p
        }//i
   }//while 
   for(int i=0;i<Finalk;i++)
       if(FinalSize[i]!=MergeCenterResult.ClusterSize[i])
           cout<<"Unexpected Merging Result!"<<endl;       
   for(int i=0;i<Finalk;i++)
   {
       FinalMembership[i]=new string[FinalSize[i]];
       for(int j=0;j<FinalSize[i];j++)
           FinalMembership[i][j]=TempFinalMembership[i][j];
   }
   
   //*********Free Memory*****************
   for(int i=0; i<Finalk; i++)
   {
        delete[] MergeCenterResult.ClusterMember[i];
        delete[] MergeCenterResult.ClusterCenterID[i];
        delete[] MergeCenterResult.ClusterCenterSeq[i];
        delete[] TempFinalMembership[i];
   }
   delete[] MergeCenterResult.ClusterMember;
   delete[] MergeCenterResult.ClusterCenterID;
   delete[] MergeCenterResult.ClusterCenterSeq;
   delete MergeCenterResult.ClusterStandardDeviation;
   delete MergeCenterResult.ClusterSize;
   delete[] TempFinalMembership;
   //**************************************
                                              
   return;                      
}

void InterResultRead(int iter)
{
    fstream BlockCenters;
    Finalk=0;
    BlockCenters.open("TempCenters",ios_base::out);
    if(BlockCenters.fail())
    {
        cout<<"Fail to Open Temp File"<<endl;
        return;
    }
    int totalcluster=0;
    for(int i=0;i<Block[iter];i++)
        for(int j=0;j<BlockResult[iter][i].ClusterNumber;j++)
            totalcluster++;
    int* Shuffle;
    Shuffle=new int[totalcluster];
    int Count=0;
    for(int i=0;i<Block[iter];i++)
        for(int j=0;j<BlockResult[iter][i].ClusterNumber;j++)
        {
            Shuffle[Count]=i;
            Count++;
        }
    r = gsl_rng_alloc (gsl_rng_taus);
    gsl_rng_set(r,(unsigned int)time((time_t *)NULL));
    gsl_ran_shuffle(r,Shuffle,totalcluster,sizeof(int));
    int TempCount[Block[iter]];
    memset(TempCount,0,sizeof(int)*Block[iter]);
    for(int i=0;i<totalcluster;i++)
    {
        BlockCenters<<BlockResult[iter][Shuffle[i]].ClusterCenterID[TempCount[Shuffle[i]]]<<endl;
        BlockCenters<<BlockResult[iter][Shuffle[i]].ClusterCenterSeq[TempCount[Shuffle[i]]]<<endl;
        BlockCenters<<BlockResult[iter][Shuffle[i]].ClusterSize[TempCount[Shuffle[i]]]<<endl;
        BlockCenters<<BlockResult[iter][Shuffle[i]].ClusterStandardDeviation[TempCount[Shuffle[i]]]<<endl;
        for(int l=0;l<MIN(20,BlockResult[iter][Shuffle[i]].ClusterSize[TempCount[Shuffle[i]]]);l++)
        {
            BlockCenters<<BlockResult[iter][Shuffle[i]].ClusterMemberSeq[TempCount[Shuffle[i]]][l];
            if((i!=Block[iter]-1)||(TempCount[Shuffle[i]]!=BlockResult[iter][Shuffle[i]].ClusterNumber-1)||(l!=MIN(20,BlockResult[iter][Shuffle[i]].ClusterSize[TempCount[Shuffle[i]]])-1))
                BlockCenters<<endl;
        }//l
        Finalk++;        
        TempCount[Shuffle[i]]++;
    }//i
    BlockCenters.close();
    delete[] Shuffle;
    gsl_rng_free(r);
    cout<<"Number of Clusters in Previous Round = "<<Finalk<<endl;
    return;
} 
